//@Author: cyl
//@File: main.go
//@Time: 2023/06/23 22:42:02
package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
)

/**
1、bufio是通过缓冲来提升效率的
2、io操作本身的效率并不低，低的是频繁的访问本地磁盘的文件。所以bufio就提供了缓冲区(分配一块内存)，读和写都先在缓冲区中，最后再读写文件，来降低访问本地磁盘的次数，从而提高效率
3、简单的说就是，把文件读取进缓冲 (内存） 之后再读取的时候就可以避免文件系统的io从而提高速度。同理，在进行写操作时，先把文件写入缓冲 （内存），
	然后由缓冲写入文件系统。看以上解释有人可能会表示困惑了，直接把内容->文件和内容->缓冲->文件相比， 缓冲区好像没有起到作用嘛
	其实缓冲区的设计是为了存储多次的写入，最后一口气把缓冲区内容写入文件
4、bufio封装了io.Reader或io.Writer接口对象，并创建另一个也实现了该接口的对象
5、io.Reader或io.Writer接口实现了Read和Write方法，对于实现这个接口的对象都可以使用这两个方法
*/

func main() {
	fmt.Println("")
	fileName := "./test1.txt"
	file, err := os.Open(fileName)
	if err != nil {
		return
	}
	defer file.Close()

	/**
	一、创建Reader对象
		bufio.NewReader中默认缓冲 defaultBufSize = 4096字节
		如果p中设置的字节 > defaultBufSize，则NewReader缓冲无效
		反之，如果p中设置的字节 < defaultBufSize，则io会从文件中依次读取p中设置好的字节数
	*/
	// Read()
	b1 := bufio.NewReader(file)
	p := make([]byte, 1024)
	n1, err := b1.Read(p)
	if err != nil {
		return
	}
	fmt.Println("Read 一共读取字节数:", n1)
	fmt.Println("Read 读取到的文本内容:", p[:n1])

	// ReadLine(): 默认读取文件行 ---> 不建议使用
	b2 := bufio.NewReader(file)
	line, isPrefix, err := b2.ReadLine()
	fmt.Println("ReadLine line:", line)
	fmt.Println("ReadLine isPrefix:", isPrefix)
	fmt.Println("ReadLine err:", err)
	fmt.Println("ReadLine 格式化好的数据:", string(line))

	// ReadString()
	b3 := bufio.NewReader(file)
	for {
		data, err := b3.ReadString('\n')
		if err == io.EOF {
			fmt.Println("文件读取结束!")
			break
		}
		if len(data) != 0 && data != "\r" && data != "\n" {
			fmt.Println("ReadLine Data:", data)
			// fmt.Println("typeof:", reflect.TypeOf(data), data == "", len(data) == 0)
		}
	}

	// ReadBytes()
	b4 := bufio.NewReader(file)
	data, err := b4.ReadBytes('\n')
	fmt.Println("ReadBytes err:", err)
	fmt.Println("ReadBytes data:", string(data))

	// os.Stdin: 读取键盘输入
	// b5 := bufio.NewReader(os.Stdin)
	// os_data, _ := b5.ReadString('\n')
	// fmt.Println("os.Stdin data:", os_data)

	/**
	二、创建Writer对象
	1、与Reader类似，将数据写入缓冲区，且需要满足p的大小与默认缓冲值的比较
	*/
	fileNameWrite := "./test2.txt"
	wfile, werr := os.OpenFile(fileNameWrite, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0655)
	if werr != nil {
		return
	}
	defer wfile.Close()

	w1 := bufio.NewWriter(wfile)
	writeLen, writeErr := w1.WriteString("hello, world!\n")
	fmt.Println("writeLen, writeErr:", writeLen, writeErr)
	w1.Flush() // 刷新缓冲区，将数据写入文件
}
